﻿using LeederBll.LogisticsAndong;
using LeederEntity.LogisticsAndong;
using LogisticsAndong.Comm;
using LogisticsAndong.opc;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using TitaniumAS.Opc.Client.Common;
using TitaniumAS.Opc.Client.Da;

namespace LogisticsAndongTest
{
    public partial class Form1 : Form
    {
        List<EntitySignalLampDirection> signalLampDirectionList;
        List<EntitySystemDevice> systemDeviceList;
        List<EntityOpcDevice> opcDeviceList;
        List<EntityOpcGroup> opcGroupList;
        List<EntityOpcTag> opcTagList;
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            InitOpcDaServer();
        }

        /// <summary>
        /// 初始化OpcServer
        /// </summary>
        private void InitOpcDaServer()
        {
            BllOpcConnect bllOpcConnect = new BllOpcConnect();
            BllOpcDevice bllOpcDevice = new BllOpcDevice();
            BllOpcGroup bllOpcGroup = new BllOpcGroup();
            BllOpcTag bllOpcTag = new BllOpcTag();
            BllSignalLampDirection bllSignalLampDirection = new BllSignalLampDirection();
            BllSystemDevice bllSystemDevice = new BllSystemDevice();

            signalLampDirectionList = bllSignalLampDirection.GetInfoList();
            systemDeviceList = bllSystemDevice.GetInfoList();

            //获取OPC的 连接 组 TAG
            EntityOpcConnect opcConnect = bllOpcConnect.GetEntity();
            opcDeviceList = bllOpcDevice.GetInfoList();
            opcGroupList = bllOpcGroup.GetInfoList();
            opcTagList = bllOpcTag.GetInfoList();
            GolbalVariable.OpcTagBag = new ConcurrentBag<EntityOpcTag>(opcTagList);
            GolbalVariable.SignalLampDirectionBag = new ConcurrentBag<EntitySignalLampDirection>(signalLampDirectionList);
            GolbalVariable.OpcHelper = new OpcHelper();
            GolbalVariable.OpcDaGroupList = new List<OpcDaGroup>();

            var tags = opcTagList.Where(t => t.group_id == 300001).ToList();

            cbSYSJ1.DataSource = tags.Select(x => x.signal_mark).ToArray();
            cbSYSJ1.SelectedIndex = 0;
            cbSYSJ2.DataSource = tags.Select(x => x.signal_mark).ToArray();
            cbSYSJ2.SelectedIndex = 0;
            cbLS.DataSource = signalLampDirectionList.Select(x => x.lamp_name).ToArray();
            cbLS.SelectedIndex = 0;
            cbSB.DataSource = systemDeviceList.Select(x => x.device_name).ToArray();
            cbSB.SelectedIndex = 0;
            string[] items = { "正常", "异常"};
            cbSBZT.DataSource = items;
            cbSBZT.SelectedIndex = 0;

            try
            {
                //获取服务名称，并创建URL
                Uri uri = UrlBuilder.Build(opcConnect.opc_server_prog_id);
                GolbalVariable.OpcHelper.opcServer = new OpcDaServer(uri);
                //绑定事件，并且启动OPC重连线程
                GolbalVariable.OpcHelper.opcServer.ConnectionStateChanged += GolbalVariable.OpcHelper.Server_ConnectionStateChanged;
                GolbalVariable.OpcHelper.opcServer.Shutdown += GolbalVariable.OpcHelper.Server_Shutdown;
                GolbalVariable.OpcHelper.opcServer.Connect();

                //依次遍历opcDevices->opcGroups->opcTags，创建OPC分组，并绑定ValuesChanged事件
                var opcDevices = opcDeviceList.Where(p => p.connect_id == opcConnect.connect_id);
                foreach (EntityOpcDevice opcDevice in opcDevices)
                {
                    var opcGroups = opcGroupList.Where(p => p.device_id == opcDevice.device_id);
                    foreach (EntityOpcGroup opcGroup in opcGroups)
                    {
                        OpcDaGroup opcDaGroup = GolbalVariable.OpcHelper.opcServer.AddGroup(opcGroup.group_name);
                        List<OpcDaItemDefinition> list = new List<OpcDaItemDefinition>();
                        var opcTags = opcTagList.Where(p => p.group_id == opcGroup.group_id);
                        if (opcTags.Count() == 0) continue;
                        foreach (EntityOpcTag opcTag in opcTags)
                        {
                            if (string.IsNullOrEmpty(opcTag.tag_name))
                                continue;
                            string ItemId = opcDevice.device_name + "." + opcGroup.group_name + "." + opcTag.tag_name;
                            list.Add(new OpcDaItemDefinition { ItemId = ItemId, IsActive = true });
                            opcTag.tag_name = ItemId;
                        }
                        var results = opcDaGroup.AddItems(list);
                        opcDaGroup.UpdateRate = TimeSpan.FromMilliseconds(opcGroup.update_rate);

                        opcDaGroup.IsActive = true;
                        opcDaGroup.IsSubscribed = true;
                        GolbalVariable.OpcDaGroupList.Add(opcDaGroup);
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }

        private static void LipXh(OpcDaGroup opcGroup, string tagName,int time)
        {
            List<string> validate = new List<string>();
            List<object> values_0 = new List<object>();
            List<object> values_1 = new List<object>();
            validate.Add(tagName);
            values_0.Add(0);
            values_1.Add(1);
            while (true)
            {
                GolbalVariable.OpcHelper.WriteValue(opcGroup, validate, values_1);
                Thread.Sleep(200);
                GolbalVariable.OpcHelper.WriteValue(opcGroup, validate, values_0);
                Thread.Sleep(time);
            }
        }

        private void btnKK_Click(object sender, EventArgs e)
        {
            var opcGroup = GolbalVariable.OpcDaGroupList.Where(p => p.Name == "KK").FirstOrDefault();
            var tags = GolbalVariable.OpcTagBag.Where(t => t.group_id == 300006).ToList();

            List<string> validate = new List<string>();
            List<object> values = new List<object>();

            tags.ForEach(x =>
            {
                var control = this.groupBox1.Controls.Find(x.tag_code, true);
                if (control != null && control.Length > 0)
                {
                    TextBox tb = control[0] as TextBox;
                    validate.Add(x.tag_name);
                    values.Add(tb.Text);
                }
            });
            GolbalVariable.OpcHelper.WriteValue(opcGroup, validate, values);
        }

        private void btnSYSJ_DC_Click(object sender, EventArgs e)
        {
            var opcGroup = GolbalVariable.OpcDaGroupList.Where(p => p.Name == "LIP").FirstOrDefault();
            var tag = GolbalVariable.OpcTagBag.Where(x => x.signal_mark == cbSYSJ1.SelectedValue.ToString()).FirstOrDefault();
            List<string> validate = new List<string>();
            List<object> values_0 = new List<object>();
            List<object> values_1 = new List<object>();
            validate.Add(tag.tag_name);
            values_0.Add(0);
            values_1.Add(1);
            GolbalVariable.OpcHelper.WriteValue(opcGroup, validate, values_1);
            Thread.Sleep(200);
            GolbalVariable.OpcHelper.WriteValue(opcGroup, validate, values_0);
        }

        Thread thread;
        private void btnSYSJ_XH_Click(object sender, EventArgs e)
        {
            if(btnSYSJ_XH.Text == "开始模拟连续触发")
            {
                var opcGroup = GolbalVariable.OpcDaGroupList.Where(p => p.Name == "LIP").FirstOrDefault();
                var tag = GolbalVariable.OpcTagBag.Where(x => x.signal_mark == cbSYSJ2.SelectedValue.ToString()).FirstOrDefault();
                if(string.IsNullOrEmpty(txtTime.Text.ToString().Trim()))
                {
                    MessageBox.Show("请输入间隔时间！");
                    return;
                }
                int time = int.Parse(txtTime.Text.ToString()) * 1000;
                thread = new Thread(delegate ()
                {
                    LipXh(opcGroup, tag.tag_name, time);
                });
                thread.Start();
                btnSYSJ_XH.Text = "停止模拟连续触发";
            }
            else
            {
                thread.Abort();
                btnSYSJ_XH.Text = "开始模拟连续触发";
            }
        }

        private void btnLS_Click(object sender, EventArgs e)
        {
            var opcGroup = GolbalVariable.OpcDaGroupList.Where(p => p.Name == "LSZT").FirstOrDefault();
            var lamp = GolbalVariable.SignalLampDirectionBag.Where(x => x.lamp_name == cbLS.SelectedValue.ToString()).FirstOrDefault();
            var tag = GolbalVariable.OpcTagBag.Where(x => x.tag_address == lamp.control_input_address).FirstOrDefault();
            if (tag == null)
            {
                MessageBox.Show("拉绳灯(" + lamp.lamp_name + ")未绑定拉绳点，请检查确认！");
                return;
            }
            List<string> validate = new List<string>();
            List<object> values_0 = new List<object>();
            List<object> values_1 = new List<object>();
            validate.Add(tag.tag_name);
            values_0.Add(0);
            values_1.Add(1);
            GolbalVariable.OpcHelper.WriteValue(opcGroup, validate, values_1);
            Thread.Sleep(200);
            GolbalVariable.OpcHelper.WriteValue(opcGroup, validate, values_0);
        }

        private void btnSB_Click(object sender, EventArgs e)
        {
            var opcGroup = GolbalVariable.OpcDaGroupList.Where(p => p.Name == "SBJK").FirstOrDefault();
            var device = systemDeviceList.Where(x => x.device_name == cbSB.SelectedValue.ToString()).FirstOrDefault();
            var tag = GolbalVariable.OpcTagBag.Where(x => x.signal_mark == device.signal_mark).FirstOrDefault();
            if (tag == null)
                return;
            List<string> validate = new List<string>();
            List<object> values = new List<object>();
            if (cbSBZT.SelectedValue.ToString() == "正常")
            {
                validate.Add(tag.tag_name);
                values.Add(0);
            }
            else
            {
                validate.Add(tag.tag_name);
                values.Add(1);
            }
            GolbalVariable.OpcHelper.WriteValue(opcGroup, validate, values);
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            try
            {
                thread.Abort();
            }
            catch(Exception ex)
            {

            }
        }
    }
}
